package com.yz.jdd.scan;

import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.google.zxing.Result;
import com.yz.jdd.scan.camera.CameraManager;
import com.yz.jdd.scan.decoding.CaptureHandler;
import com.yz.jdd.scan.decoding.CaptureListener;
import com.yz.jdd.scan.view.ViewfinderView;


import java.io.IOException;

/**
 * Created by shibin on 2017/1/13.
 */

public class SoftwareScanner implements Scanner, SurfaceHolder.Callback {
    private Context context;
    private static SoftwareScanner INSTANCE;
    private boolean hasSurface;
    private ScanEventListener scanEventListener;
    private CaptureHandler captureHandler;
    private ViewfinderView viewfinderView;
    private SurfaceHolder surfaceHolder;
    private volatile boolean isStart = false;
    private boolean isScanable = false;
    private Handler uiHandler;
    private Object uiObj = new Object();
    private SoftwareScanner(Context context) {
        this.context = context.getApplicationContext();
        hasSurface = false;
    }

    public static SoftwareScanner getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new SoftwareScanner(context);
        }
        return INSTANCE;
    }

    @Override
    public void init(SurfaceView surfaceView, ViewfinderView viewfinderView) {
        //初始化相机
        CameraManager.init(context.getApplicationContext());
        this.viewfinderView = viewfinderView;
        if (surfaceView == null || viewfinderView == null)
            return;
        surfaceHolder = surfaceView.getHolder();
    }

    @Override
    public void doScan(ScanEventListener scanEventListener, boolean isScanable) {
        if (isStart)
            return;
        isStart = true;
        this.scanEventListener = scanEventListener;
        this.isScanable = isScanable;
        startScan(isScanable);
    }

    @Override
    public CaptureHandler getCaptureHandler() {
        return captureHandler != null ? captureHandler : null;
    }

    @Override
    public void release() {
        stopScan();
        scanEventListener = null;
        viewfinderView = null;
        surfaceHolder = null;
    }

    private void initCamera(SurfaceHolder surfaceHolder, boolean isScanable) {
        try {
            CameraManager.get().openDriver(surfaceHolder);
        } catch (IOException ioe) {
            scanEventListener.onError();
            return;
        } catch (RuntimeException e) {
            scanEventListener.onError();
            return;
        }

        if (captureHandler == null) {

            captureHandler = new CaptureHandler(viewfinderView, new CaptureListener() {
                @Override
                public void onCaptureSuccess(Result result) {
                    stopScan();
                    if (scanEventListener != null)
                        scanEventListener.onSuccess(result);
                }
            }, null, null, isScanable);
        }
    }

    public void startScan(boolean isScanable) {
        if (hasSurface) {
            initCamera(surfaceHolder, isScanable);
        } else {
            surfaceHolder.addCallback(this);
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){
                surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            }

        }
    }

    public void stopScan() {
        isStart = false;
        if (captureHandler != null) {
            captureHandler.quitSynchronously();
            captureHandler = null;
        }
        if (CameraManager.get() != null) {
            CameraManager.get().closeDriver();
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (!hasSurface) {
            hasSurface = true;
            initCamera(holder, isScanable);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;
    }
}
